<script setup lang="ts">
import { onMounted, ref } from 'vue'
import {
  RenderingEngine,
  Types,
  Enums,
  setVolumesForViewports,
  volumeLoader,
  utilities,
  geometryLoader,
  CONSTANTS,
} from '@cornerstonejs/core'
import {
  initDemo,
  createImageIdsAndCacheMetaData

} from '@/helpers'
import assetsURL from '@/assets/assetsURL.json'
import * as cornerstoneTools from '@cornerstonejs/tools'
const {
  SegmentationDisplayTool,
  ToolGroupManager,
  Enums: csToolsEnums,
  segmentation,
  ZoomTool,
  Types,
  TrackballRotateTool,
  PanTool, StackScrollMouseWheelTool
} = cornerstoneTools
const { MouseBindings } = csToolsEnums
const { ViewportType, GeometryType } = Enums
const singleViewContainerRef = ref(null)
const renderContainerRef = ref(null)
const volumeName = 'CT_VOLUME_ID' // Id of the volume less loader prefix
const volumeLoaderScheme = 'cornerstoneStreamingImageVolume' // Loader id which defines which volume loader to use
const volumeId = `${volumeLoaderScheme}:${volumeName}` // VolumeId with loader id + volume id

const toolGroupId = '2d_View_ToolGroup_With_Contour'
const toolGroupId3d = '3d_View_ToolGroup_With_Contour'
const segmentationId = 'MY_SEGMENTATION_ID'
const viewportId2 = 'CT_3D'
const viewportId1 = 'CT_AXIAL'
let renderingEngine
let geometryIds = []
const renderingEngineId = 'Surface_With_Contour_RenderingEngine'
let toolGroup
let toolGroup3d

async function addSegmentationsToState() {
  const contour = await fetch(assetsURL.CircleContour).then((res) =>
    res.json()
  )
  const promises = contour.contourSets.map((contourSet) => {
    const geometryId = contourSet.id
    geometryIds.push(geometryId)
    return geometryLoader.createAndCacheGeometry(geometryId, {
      type: GeometryType.CONTOUR,
      geometryData: contourSet as Types.PublicContourSetData
    })
  })

  await Promise.all(promises)

  segmentation.addSegmentations([
    {
      segmentationId,
      representation: {
        // The type of segmentation
        type: csToolsEnums.SegmentationRepresentations.Contour,
        // The actual segmentation data, in the case of contour geometry
        // this is a reference to the geometry data
        data: {
          geometryIds
        }
      }
    }
  ])
}

const initTools = () => {
  init2DTools()
  init3DTools()
}

const init2DTools = () => {
  toolGroup = ToolGroupManager.createToolGroup(toolGroupId)
  if (!toolGroup) {
    return
  }
  toolGroup.addTool(SegmentationDisplayTool.toolName)
  toolGroup.addTool(PanTool.toolName)
  toolGroup.addTool(ZoomTool.toolName)
  toolGroup.addTool(StackScrollMouseWheelTool.toolName)

  toolGroup.setToolEnabled(SegmentationDisplayTool.toolName)

  toolGroup.setToolActive(PanTool.toolName, {
    bindings: [
      {
        mouseButton: MouseBindings.Auxiliary // Middle Click
      }
    ]
  })
  toolGroup.setToolActive(ZoomTool.toolName, {
    bindings: [
      {
        mouseButton: MouseBindings.Secondary // Right Click
      }
    ]
  })

  toolGroup.setToolActive(StackScrollMouseWheelTool.toolName)
}

const init3DTools = () => {
  toolGroup3d = ToolGroupManager.createToolGroup(toolGroupId3d)
  if (!toolGroup3d) {
    return
  }
  toolGroup3d.addTool(SegmentationDisplayTool.toolName)
  toolGroup3d.addTool(ZoomTool.toolName)
  toolGroup3d.addTool(TrackballRotateTool.toolName, {
    configuration: { volumeId }
  })

  toolGroup3d.setToolEnabled(SegmentationDisplayTool.toolName)


  toolGroup3d.setToolActive(TrackballRotateTool.toolName, {
    bindings: [
      {
        mouseButton: MouseBindings.Primary
      }
    ]
  })

  toolGroup3d.setToolActive(ZoomTool.toolName, {
    bindings: [
      {
        mouseButton: MouseBindings.Secondary // Right Click
      }
    ]
  })
}

async function run() {
  // Init Cornerstone and related libraries
  await initDemo()
  initTools()

  // Get Cornerstone imageIds for the source data and fetch metadata into RAM
  const imageIds = await createImageIdsAndCacheMetaData({
    StudyInstanceUID:
      '1.3.6.1.4.1.14519.5.2.1.7009.2403.334240657131972136850343327463',
    SeriesInstanceUID:
      '1.3.6.1.4.1.14519.5.2.1.7009.2403.226151125820845824875394858561',
    wadoRsRoot: 'https://d3t6nz73ql33tx.cloudfront.net/dicomweb'
  })

  // Define a volume in memory
  const volume = await volumeLoader.createAndCacheVolume(volumeId, {
    imageIds
  })

  // Add some segmentations based on the source data volume
  await addSegmentationsToState()

  // Instantiate a rendering engine
  renderingEngine = new RenderingEngine(renderingEngineId)

  const viewportInputArray = [
    {
      viewportId: viewportId1,
      type: ViewportType.ORTHOGRAPHIC,
      element: singleViewContainerRef.value,
      defaultOptions: {
        orientation: Enums.OrientationAxis.AXIAL,
        background: <Types.Point3>[0.2, 0, 0.2]
      }
    },
    {
      viewportId: viewportId2,
      type: ViewportType.VOLUME_3D,
      element: renderContainerRef.value,
      defaultOptions: {
        background: <Types.Point3>[0.2, 0, 0.2]
      }
    }
  ]

  renderingEngine.setViewports(viewportInputArray)
  toolGroup.addViewport(viewportId1, renderingEngineId)
  toolGroup3d.addViewport(viewportId2, renderingEngineId)
  volume.load()
  setVolumesForViewports(
    renderingEngine,
    [{ volumeId }],
    [viewportId1, viewportId2]
  ).then(() => {
    const viewport3d = renderingEngine.getViewport(viewportId2)
    const volumeActor = viewport3d.getDefaultActor().actor as Types.VolumeActor
    // 这里和体绘制采用的参数好像一样。
    utilities.applyPreset(
      volumeActor,
      CONSTANTS.VIEWPORT_PRESETS.find(
        (preset) => preset.name === 'CT-Bone'
      ) as any
    )

    const renderer = viewport3d.getRenderer()
    renderer.getActiveCamera().elevation(-70)
    viewport3d.setCamera({ parallelScale: 600 })

    viewport3d.render()
  })

  // // Add the segmentation representation to the toolgroup
  await segmentation.addSegmentationRepresentations(toolGroupId, [
    {
      segmentationId,
      type: csToolsEnums.SegmentationRepresentations.Contour
    }
  ])

  await segmentation.addSegmentationRepresentations(toolGroupId3d, [
    {
      segmentationId,
      type: csToolsEnums.SegmentationRepresentations.Contour
    }
  ])
  renderingEngine.render()
}

onMounted(() => {
  run()
})

</script>

<template>
  <div class="w-[900px] h-[500px] flex">
    <div class="w-1/2 h-full" ref="singleViewContainerRef"></div>
    <div class="w-1/2 h-full bg-transparent  relative" ref="renderContainerRef">
    </div>
  </div>
</template>

<style scoped>

</style>
